package com.tbit.uqbike.webmanager.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tbit.common.constant.MethodEnum;
import com.tbit.common.constant.ModuleEnum;
import com.tbit.common.constant.OperationPlatform;
import com.tbit.common.entity.UserOpLog;
import com.tbit.common.entity.view.PageResult;
import com.tbit.common.entity.view.Result;
import com.tbit.common.enums.OperaPswEnum;
import com.tbit.uqbike.annos.OperateLog;
import com.tbit.uqbike.constant.UserConstant;
import com.tbit.uqbike.enums.SystemCodeEnum;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.pojo.Coupon;
import com.tbit.uqbike.object.pojo.CouponGiftLog;
import com.tbit.uqbike.object.pojo.CouponUser;
import com.tbit.uqbike.object.pojo.dto.CouponBatchGiftDTO;
import com.tbit.uqbike.object.pojo.dto.PackageDelayDTO;
import com.tbit.uqbike.object.pojo.vo.GiveRideCardVo;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.object.view.JsonResult;
import com.tbit.uqbike.service.business.AccountService;
import com.tbit.uqbike.service.business.CouponService;
import com.tbit.uqbike.service.business.OperaPswService;
import com.tbit.uqbike.service.rpcservice.PurviewService;
import com.tbit.uqbike.webmanager.business.user_op_log.service.UserOpLogService;
import com.tbit.uqbike.webmanager.util.Assert;
import com.tbit.uqbike.webmanager.util.ServletUtils;
import com.tbit.uqbike.webmanager.util.excel.ExcelUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 优惠券
 *
 * @author chenmengran
 * @Description: 优惠券
 * @date 2019\12\27 002716:38
 */
@Validated
@RestController
@RequestMapping(value = "/coupon", produces = BaseController.MEDIA_JSON_UTF8)
public class CouponController extends BaseController {
    @Autowired
    private CouponService couponService;
    @Autowired
    private PurviewService purviewService;
    @Autowired
    private UserOpLogService userOpLogService;
    @Autowired
    private AccountService accountService;
    @Autowired
    private OperaPswService operaPswService;

    // 添加优惠券
    @RequestMapping("/add")
    @OperateLog(module = ModuleEnum.COUPON, methods = MethodEnum.COUPON_ADD)
    public JsonResult add(Coupon coupon,
                          @NotNull(message = "ver.startTime.notNull") Long startTime,
                          @NotNull(message = "ver.endTime.notNull") Long endTime,
                          HttpServletRequest request) {

        if (StrUtil.isNotEmpty(coupon.getName()) && coupon.getName().length() > 50){
            throw new BaseException("优惠券名称过长");
        }
        if (StrUtil.isNotEmpty(coupon.getRemark()) && coupon.getRemark().length() > 500){
            throw new BaseException("优惠券使用说明过长");
        }

        coupon.setStartTime(new Date(startTime));
        coupon.setEndTime(new Date(endTime));

        // 获取用户信息
        LoginInfo loginInfo = getLogin(request);
        if (!loginInfo.type.equals(UserConstant.USER_AGENT)) {
            Assert.notNull(coupon.getAccountId(), "ver.accountId .notNull");
        } else {
            coupon.setAccountId(loginInfo.id);
        }
        couponService.add(loginInfo, coupon);

        // 插入用户操作日志
        userOpLogService.insertSingle(UserOpLog.builder()
                .accountId(coupon.getAccountId())
                .opUser(loginInfo.getName())
                .opUserPhone(loginInfo.getPhone())
                .operation("优惠券变动")
                .opType("创建")
                .opPlatform(OperationPlatform.MANAGER.code)
                .opTime(LocalDateTime.now())
                .detail("优惠券名称: " + coupon.getName())
                .result(true)
                .build());

        return JsonResult.ok();
    }

    // 添加优惠券
    @RequestMapping("/update")
    @OperateLog(module = ModuleEnum.COUPON, methods = MethodEnum.COUPON_UPDATE)
    public JsonResult update(Coupon coupon, HttpServletRequest request) {

        LoginInfo loginInfo = getLogin(request);
        Assert.notNull(coupon.getCouponId(), "ver.couponId.notNull");
        Assert.notNull(coupon.getIsValid(), "ver.isValid.notNull");
        if (StrUtil.isNotEmpty(coupon.getName()) && coupon.getName().length() > 50){
            throw new BaseException("优惠券名称过长");
        }
        if (StrUtil.isNotEmpty(coupon.getRemark()) && coupon.getRemark().length() > 500){
            throw new BaseException("优惠券使用说明过长");
        }
        couponService.update(coupon);

        // 插入用户操作日志
        userOpLogService.insertSingle(UserOpLog.builder()
                .accountId(coupon.getAccountId())
                .opUser(loginInfo.getName())
                .opUserPhone(loginInfo.getPhone())
                .operation("优惠券变动")
                .opType("修改")
                .opPlatform(OperationPlatform.MANAGER.code)
                .opTime(LocalDateTime.now())
                .detail("优惠券ID: " + coupon.getCouponId())
                .result(true)
                .build());

        return JsonResult.ok();
    }

    // 查询优惠券
    @RequestMapping("/getCoupon")
    public JsonResult getCoupon(Integer accountId,
                                @RequestParam(defaultValue = "10") Integer rowCount,
                                @RequestParam(defaultValue = "1") Integer pageNO,
                                HttpServletRequest request) {
        // 获取用户信息
        LoginInfo loginInfo = getLogin(request);
        if (!loginInfo.type.equals(UserConstant.USER_AGENT)) {
            Assert.notNull(accountId, "ver.accountId .notNull");
        } else {
            accountId = loginInfo.id;
        }
        List<Coupon> coupons = couponService.queryPage(loginInfo, accountId, pageNO, rowCount);
        Integer total = couponService.queryCount(accountId);

        return JsonResult.ok(coupons, total);
    }

    /**
     * 获取代理商所有可以优惠券
     *
     * @param accountId
     * @param request
     * @return
     */
    @RequestMapping("/getCouponIsVail")
    public JsonResult getCouponIsVail(Integer accountId, HttpServletRequest request) {
        // 获取用户信息
        LoginInfo loginInfo = getLogin(request);
        if (!loginInfo.type.equals(UserConstant.USER_AGENT)) {
            Assert.notNull(accountId, "ver.accountId .notNull");
        } else {
            accountId = loginInfo.id;
        }

        if (!purviewService.purviewCheck(loginInfo.id, accountId)) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }

        List<Coupon> coupons = couponService.getCouponIsVail(accountId);

        return JsonResult.ok(coupons);
    }

    /**
     * 查询用户优惠券
     *
     * @param userId
     * @param rowCount
     * @param pageNO
     * @return
     */
    @RequestMapping("/userCouponPage")
    public JsonResult userCouponPage(Integer userId, Integer accountId,
                                     @RequestParam(defaultValue = "10") Integer rowCount,
                                     @RequestParam(defaultValue = "1") Integer pageNO) {

        Assert.notNull(userId, "ver.userId .notNull");

        List<CouponUser> coupons = couponService.getByUserIdPage(userId, accountId, pageNO, rowCount);
        Integer total = couponService.getByUserIdCount(userId, accountId);

        return JsonResult.ok(coupons, total);
    }


    /**
     * 查询优惠劵赠送记录
     *
     * @param accountId 运营区域id
     * @param userPhone 用户手机号
     * @param rowCount  每页条数
     * @param pageNO    页码
     * @return 。
     */
    @GetMapping("/gift/log")
    public Result<PageResult<CouponGiftLog>> userCouponPage(@RequestParam Integer accountId, String userPhone, Date startTime, Date endTime,
                                                            @RequestParam(defaultValue = "10") Integer rowCount,
                                                            @RequestParam(defaultValue = "1") Integer pageNO) {
        CouponGiftLog couponGiftLog = new CouponGiftLog();
        couponGiftLog.setUserPhone(userPhone);
        couponGiftLog.setRegionId(accountId);
        PageInfo<CouponGiftLog> pageInfo = PageHelper.startPage(pageNO, rowCount).doSelectPageInfo(() -> couponService.listCouponGiftLog(couponGiftLog, startTime, endTime));
        return Result.success(new PageResult<>(pageNO, rowCount, pageInfo.getTotal(), pageInfo.getPages(), pageInfo.getList()));
    }


    /**
     * 优惠劵赠送记录
     * @param accountId 运营区域id
     * @param userPhone 用户手机号
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return fileName
     */
    @GetMapping("/exportGift")
    public Result<Object> exportGift(@RequestParam Integer accountId, String userPhone, Date startTime, Date endTime) {
        CouponGiftLog couponGiftLog = new CouponGiftLog();
        couponGiftLog.setUserPhone(userPhone)
                        .setRegionId(accountId);
        List<CouponGiftLog> list = couponService.listCouponGiftLog(couponGiftLog, startTime, endTime);

        String fileName = "优惠券赠送记录";
        if (Objects.nonNull(startTime) && Objects.nonNull(endTime)){
            if (DateUtil.betweenMonth(startTime, endTime, true) > 6){
                return Result.error("仅允许导出6个月的数据");
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            fileName = String.format("%s~%s 优惠券赠送记录", sdf.format(startTime), sdf.format(endTime));
        }

        ExcelUtil<CouponGiftLog> excelUtil = new ExcelUtil<>(CouponGiftLog.class);
        JsonResult result = excelUtil.exportExcel(list, fileName);
        return Result.success(result.getData());
    }

    /**
     * 批量赠送用户优惠券
     *
     * @param couponUser
     * @param num
     * @return
     */
    @RequestMapping("/addBatch")
    @OperateLog(module = ModuleEnum.COUPON, methods = MethodEnum.COUPONUSER_ADD)
    public JsonResult addBatch(CouponUser couponUser, @RequestParam(defaultValue = "1") Integer num, Long endTime,
                               Boolean sendMessage, HttpServletRequest request) {
        Assert.notNull(couponUser.getUserId(), "ver.userId.notNull");
        Assert.notNull(couponUser.getCouponId(), "ver.couponId.notNull");
        Assert.notNull(endTime, "请填写失效时间");
        LoginInfo loginInfo = getLogin(request);
        couponService.addBatch(couponUser, num, endTime, sendMessage, loginInfo);

        return JsonResult.ok();
    }

    /**
     * 批量赠送优惠劵
     *
     * @param giftDTO 对象优惠劵
     * @return 。
     */
    @PostMapping("/batch/gift")
    @OperateLog(module = ModuleEnum.COUPON, methods = MethodEnum.COUPONUSER_BATCH_SEND)
    public Result<List<GiveRideCardVo>> addBatchCoupons(@Validated CouponBatchGiftDTO giftDTO, HttpServletRequest request) {

        LoginInfo loginInfo = getLogin(request);
        /**操作密码校验*/
        operaPswService.checkOperaPsw(loginInfo, OperaPswEnum.OPERA_PSW_COUPONS_CONFIG.getModule(), giftDTO.getPwd());

        giftDTO.setLoginInfo(loginInfo);
        return couponService.addBatchCoupons(giftDTO);
    }

    /**
     * 延长优惠券到期时间
     *
     * @param delayDTO .
     * @return .
     */
    @PostMapping("/modifyExpireTime")
    @OperateLog(module = ModuleEnum.COUPON, methods = MethodEnum.COUPONUSER_Edit)
    public Result<String> modifyExpireTime(@RequestBody @Validated PackageDelayDTO delayDTO) {
        delayDTO.valid("优惠劵");
        operaPswService.checkOperaPsw(BaseController.getLogin(ServletUtils.getRequest()),
                OperaPswEnum.OPERA_PSW_COUPONS_CONFIG.getModule(), delayDTO.getPwd());
        couponService.modifyCouponExpireTime(delayDTO);
        return Result.success();
    }


    /**
     * @param allFailures
     * @param couponUserId 根据用户优惠券id置为失效
     * @param userId       根据用户将优惠券全部置为失效
     * @return com.tbit.uqbike.object.view.JsonResult
     * @Description:
     * @createDate 2020/12/23 11:54
     */
    @PostMapping("/userCouponEdit")
    @OperateLog(module = ModuleEnum.COUPON, methods = MethodEnum.COUPONUSER_Edit)
    public JsonResult userCouponEdit(Boolean allFailures, Integer couponUserId, Integer userId) {
        if ((allFailures == null || !allFailures) && (null == couponUserId)) {
            throw new BaseException(SystemCodeEnum.PLEASE_SELECT_COUPON);
        }
        if (allFailures != null && allFailures && null == userId) {
            throw new BaseException(SystemCodeEnum.PLEASE_SELECT_COUPON);
        }
        couponService.userCouponEdit(couponUserId, userId);
        return JsonResult.ok();
    }
}
